//
//  AppDelegate.m
//  reghotkeyapp
//
//  Created by flynn on 2025/2/26.
//

#import "AppDelegate.h"
#import <Cocoa/Cocoa.h>
#import <Carbon/Carbon.h>
@interface AppDelegate ()
{
    EventHotKeyRef _altCKeyRef;
}
@end



@implementation AppDelegate

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
    // 注册 Alt+C 热键
    if (![self registerHotKeyForKeyCode:8 modifiers:optionKey signature:'htk1' id:1]) {
        NSLog(@"Failed to register Alt+C hot key.");
    }
}

- (BOOL)registerHotKeyForKeyCode:(UInt32)keyCode modifiers:(OptionBits)modifiers signature:(FourCharCode)signature id:(UInt32)id1 {
    EventHotKeyID hotKeyID;
    hotKeyID.signature = signature;
    hotKeyID.id = id1;

    EventTypeSpec eventType;
    eventType.eventClass = kEventClassKeyboard;
    eventType.eventKind = kEventHotKeyReleased;

    OSStatus status = RegisterEventHotKey(keyCode, modifiers, hotKeyID, GetEventDispatcherTarget(),kEventHotKeyExclusive, &_altCKeyRef);
    if (status != noErr) {
        NSLog(@"Error code from RegisterEventHotKey: %ld", status);
        return NO;
    }

    EventHandlerRef eventHandlerRef = NewEventHandlerUPP((EventHandlerProcPtr)HotKeyHandler);
    if (!eventHandlerRef) {
        NSLog(@"Failed to create event handler UPP.");
        UnregisterEventHotKey(_altCKeyRef);
        return NO;
    }

    OSStatus installStatus = InstallEventHandler(GetEventDispatcherTarget(), eventHandlerRef, 1, &eventType, (__bridge void *)(self), NULL);
    if (installStatus != noErr) {
        NSLog(@"Error code from InstallEventHandler: %ld", installStatus);
        DisposeEventHandlerUPP(eventHandlerRef);
        UnregisterEventHotKey(_altCKeyRef);
        return NO;
    }

    return YES;
}

// 热键处理函数
static OSStatus HotKeyHandler(EventHandlerCallRef nextHandler, EventRef theEvent, void *userData) {
    AppDelegate *appDelegate = (__bridge AppDelegate *)userData;
    EventHotKeyID hotKeyID;
    GetEventParameter(theEvent, kEventParamDirectObject, typeEventHotKeyID, NULL, sizeof(hotKeyID), NULL, &hotKeyID);

    if (hotKeyID.signature == 'htk1') { // Alt+C
        [appDelegate handleAltC];
    }

    return noErr;
}

- (void)handleAltC {
    NSLog(@"Alt+C 被按下");

    // 模拟 Cmd+C 以触发系统的复制操作
    [self postCommandCEvent];
}
- (void)postCommandCEvent {
    // 创建 Cmd 键按下事件
    CGEventRef commandDown = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)55, true); // 55 is the keycode for the left Command key
    // 创建 Cmd 键释放事件
    CGEventRef commandUp = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)55, false);
    // 创建 'c' 键按下事件
    CGEventRef cDown = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)8, true); // 8 is the keycode for 'c'
    // 创建 'c' 键释放事件
    CGEventRef cUp = CGEventCreateKeyboardEvent(NULL, (CGKeyCode)8, false);

    // 设置 Cmd 键标志位
    CGEventSetFlags(cDown, kCGEventFlagMaskCommand);
    CGEventSetFlags(cUp, kCGEventFlagMaskCommand);

    // 发送事件
    CGEventPost(kCGAnnotatedSessionEventTap, commandDown);
    CGEventPost(kCGAnnotatedSessionEventTap, cDown);
    CGEventPost(kCGAnnotatedSessionEventTap, cUp);
    CGEventPost(kCGAnnotatedSessionEventTap, commandUp);

    // 释放事件对象
    CFRelease(commandDown);
    CFRelease(commandUp);
    CFRelease(cDown);
    CFRelease(cUp);
}
- (void)postCommandCEvent1 {
    CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
    CGEventTapLocation loc = kCGHIDEventTap; // kCGSessionEventTap also works
    CGKeyCode inputKeyCode = kVK_ANSI_C;
    CGEventRef copyCommandDown = CGEventCreateKeyboardEvent(source, inputKeyCode, YES);
    CGEventSetFlags(copyCommandDown, kCGEventFlagMaskCommand);
    CGEventPost(loc, copyCommandDown);
    
    CGEventRef copyCommandup = CGEventCreateKeyboardEvent(source, inputKeyCode, NO);
    CGEventSetFlags(copyCommandup, kCGEventFlagMaskCommand);
    CGEventPost(loc, copyCommandup);
    CFRelease(copyCommandDown);
    CFRelease(copyCommandup);
    CFRelease(source);
}

- (void)applicationWillTerminate:(NSNotification *)aNotification {
    // 注销热键
    if (_altCKeyRef) {
        UnregisterEventHotKey(_altCKeyRef);
        _altCKeyRef = NULL;
    }
}

@end
